package com.cxz.study.ddd_project.infrastructure.service;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.cxz.study.ddd_project_parent_api.common.ResponseData;
import com.cxz.study.ddd_project_parent_common.enums.StateCode;
import com.cxz.study.ddd_project_parent_common.exception.CustomException;
import feign.RetryableException;
import org.slf4j.Logger;
import org.springframework.util.StringUtils;

import java.util.Objects;
import java.util.function.Function;

import static com.cxz.study.ddd_project_parent_common.enums.StateCode.RPC_CALL_BUSY_EXCEPTION;
import static com.cxz.study.ddd_project_parent_common.enums.StateCode.RPC_CALL_EXCEPTION;


/**
 * @className: AbstractRelationService
 * @author: ocxz1
 * @date: 2025/1/1 下午5:03
 * @Version: 1.0
 * @description: anneng-ltc-change-v1.0
 */
public abstract class AbstractRelationService implements IRelationService {

    /**
     * 参数校验
     *
     * @param t 入参数据
     */
    @Override
    public <T> boolean paramCheck(T t) {
        if (Objects.isNull(t)) {
            return true;
        }

        // 如果没有校验器，则不做数据校验
        LtcValidator ltcValidator = getLtcValidator();
        if (ltcValidator == null) {
            return true;
        }

        // 参数检查
        return ltcValidator.checkParam(t, getLogger());
    }

    /**
     * rpc服务远程调用
     * @param t 入参
     * @param callFunc 远程调用函数
     * @param convertFunc rpc服务入参转换
     * @param backConvertFunc rpc出参转换
     * @return 执行结果
     * @param <T> 入参类型
     * @param <V> 出参类型
     * @param <U> rpc调用 入参类型
     * @param <W> rpc调用 出参类型
     */
    @Override
    public <T, V, U, W> ResponseData<V> rpcCall(T t, Function<U, ResponseData<W>> callFunc,
                                                Function<T, U> convertFunc, Function<W, V> backConvertFunc) {
        return defaultCallHandle(t, callFunc, convertFunc, backConvertFunc, null, null);
    }

    /**
     * rpc服务远程调用
     * @param t 入参
     * @param callFunc 远程调用函数
     * @param convertFunc rpc服务入参转换
     * @param backConvertFunc rpc出参转换
     * @return 执行结果
     * @param <T> 入参类型
     * @param <V> 出参类型
     * @param <U> rpc调用 入参类型
     * @param <W> rpc调用 出参类型
     */
    @Override
    public <T, V, U, W> ResponseData<V> rpcCallThrow(T t, Function<U, ResponseData<W>> callFunc,
                                                Function<T, U> convertFunc, Function<W, V> backConvertFunc) {
        ResponseData<V> vResponseData = defaultCallHandle(t, callFunc, convertFunc, backConvertFunc, null, null);
        if (vResponseData == null || !vResponseData.getSuccess()) {
            throw CustomException.getException(StateCode.RPC_CALL_EXCEPTION, vResponseData != null ?
                    vResponseData.getMessage() : null);
        }
        return vResponseData;
    }

    /**
     * rpc服务远程调用，返参为空的情况
     * @param t 入参
     * @param callFunc 远程调用函数
     * @param convertFunc rpc服务入参转换
     * @return 执行结果
     * @param <T> 入参类型
     * @param <U> rpc调用 入参类型
     * @param <W> rpc调用 出参类型
     */
    public <T, U, W> ResponseData<Void> rpcCall(T t, Function<U, ResponseData<W>> callFunc, Function<T, U> convertFunc) {
        return defaultCallHandle(t, callFunc, convertFunc, null, null, null);
    }

    /**
     * rpc服务远程调用，返参数据为空的情况
     *
     * @param t           入参
     * @param callFunc    远程调用函数
     * @param convertFunc rpc服务入参转换
     * @param vClass      出参数据类型
     * @return 执行结果
     */
    @Override
    public <T, V, U, W> ResponseData<V> rpcCall(T t, Function<U, ResponseData<W>> callFunc, Function<T, U> convertFunc, Class<V> vClass) {
        return defaultCallHandle(t, callFunc, convertFunc, null, vClass, null);

    }

    /**
     * rpc服务远程调用
     * @param t 入参
     * @param callFunc 远程调用函数
     * @param convertFunc rpc服务入参转换
     * @param backConvertFunc rpc出参转换
     * @return 执行结果
     * @param <T> 入参类型
     * @param <V> 出参类型
     * @param <U> rpc调用 入参类型
     * @param <W> rpc调用 出参类型
     */
    public <T, V, U, W> ResponseData<V> rpcCallObj(T t, Function<U, W> callFunc, Function<T, U> convertFunc, Function<W, V> backConvertFunc) {

        return defaultCallHandle(t, (rpcData) -> {
            // 远程服务调用
            W apply = callFunc.apply(rpcData);

            return ResponseData.success(apply);

        }, convertFunc, backConvertFunc, null, null);
    }

    /**
     * 默认的回调处理
     * @param t 入参
     * @param callFunc 返回远程调用结果（若需要返回值转换，则内部进行）
     * @param backConvertFunc rpc出参转换
     * @return 执行结果
     * @param <T> 入参类型
     * @param <V> 出参类型
     * @param <W> rpc调用 出参类型
     */
    private  <T, V, U, W> ResponseData<V> defaultCallHandle(T t, Function<U, ResponseData<W>> callFunc,
                                                          Function<T, U> convertFunc,
                                                          Function<W, V> backConvertFunc,
                                                          Class<V> vClass,
                                                          TypeReference<V> vTypeReference) {
        // 参数校验
        boolean b = paramCheck(t);
        if (!b) {
            return ResponseData.failure(StateCode.PARAMS_NOT_ENOUGH);
        }

        Logger LOGGER = getLogger();

        try {
            // 参数转换
            U rpcData = null;
            if (Objects.nonNull(t)) {
                if (Objects.nonNull(convertFunc)) {
                    rpcData = convertFunc.apply(t);
                } else {
                    // 如果 convertFunc 没有传入，并且 t 是 U 的实例，则直接转换
                    rpcData = (U)t;
                }
            }

            // 远程服务调用
            ResponseData<W> resResponse = callFunc.apply(rpcData);

            // 执行远程服务调用
            if (resResponse == null || !Objects.equals(StateCode.SUCCESS.value, resResponse.getCode())) {
                LOGGER.warn("{} ,rpc call to the remote service failed, request: {}, response: {}", StateCode.RPC_CALL_EXCEPTION.text
                        , JSON.toJSON(rpcData), JSON.toJSON(resResponse));
                if (resResponse != null && StringUtils.hasText(resResponse.getMessage())) {
                    return ResponseData.failure(StateCode.RPC_CALL_EXCEPTION, "失败原因：", resResponse.getMessage());
                } else {
                    return ResponseData.failure(StateCode.RPC_CALL_EXCEPTION);
                }
            }
            LOGGER.info("{}, rpc call to the remote service success. request:{}, response:{}", StateCode.SUCCESS.text,
                    JSON.toJSON(rpcData), JSON.toJSON(resResponse));

            // 返回数据转换
            V resultData = null;
            if (backConvertFunc != null) {
                resultData = backConvertFunc.apply(resResponse.getData());
            } else {
                W data = resResponse.getData();
                if (Objects.nonNull(data)) {
                    resultData = (V)data;
                }
            }
            // 数据返回
            return ResponseData.success(resultData);
        } catch (Exception e) {
            if (e instanceof RetryableException) {
                LOGGER.error("{}, rpc call to the remote service error, request: {}", RPC_CALL_BUSY_EXCEPTION.text, JSON.toJSON(t), e);
                return ResponseData.failure(RPC_CALL_BUSY_EXCEPTION);
            } else {
                LOGGER.error("{}, rpc call to the remote service error, request: {}", RPC_CALL_EXCEPTION.text, JSON.toJSON(t), e);
                return ResponseData.failure(RPC_CALL_EXCEPTION);
            }
        }
    }

    /**
     * @param t
     * @param callFunc
     * @param <T>
     * @param <V>
     * @return
     */
    @Override
    public <T,V> ResponseData<V> rpcCall(T t, Function<T, ResponseData<V>> callFunc) {
        return defaultCallHandle(t, callFunc, null, null, null, new TypeReference<V>() {});
    }

    /**
     * @return 返回LTC参数校验器
     */
    @Override
    public LtcValidator getLtcValidator() {
        return null;
    }
}
